# services.py
from datetime import datetime
from flask import request
from inc.models import db, JiraProject, JiraMember, JiraStage, AdminMember, JiraApprovalFlow, JiraApprovalStep, JiraReview
from inc import logger
from sqlalchemy import or_, and_


def get_jira_projects(user_id, status_filter='all'):
    """获取用户可访问的JIRA项目列表
    - 拥有MANAGE_PROJECTS权限的用户可以看到所有项目
    - 普通成员可以看到自己负责的项目(owner)，以及自己参与且处于特定状态的项目
    """
    current_member = AdminMember.query.get(user_id)
    if not current_member:
        return []

    # 拥有MANAGE_PROJECTS权限的用户可以看到所有项目
    if current_member.has_permission('MANAGE_PROJECTS'):
        query = JiraProject.query
    else:
        # 普通成员：包含两类项目
        # 1) 该用户作为项目负责人（owner）创建的项目
        # 2) 该用户作为成员参与且状态在允许列表内的项目
        member_proj_ids = db.session.query(JiraMember.project_id).filter(JiraMember.member_id == user_id)
        allowed_statuses = [
            JiraProject.APPROVED,
            JiraProject.IN_PROGRESS,
            JiraProject.COMPLETED
        ]
        if status_filter == 'all':
            query = JiraProject.query.filter(
                or_(
                    JiraProject.owner_id == user_id,
                    and_(JiraProject.id.in_(member_proj_ids), JiraProject.status.in_(allowed_statuses))
                )
            )
        else:
            # 如果用户传入了具体 status_filter，则对所有匹配项按该状态筛选（包括 owner 的项目）
            query = JiraProject.query.filter(
                or_(
                    JiraProject.owner_id == user_id,
                    JiraProject.id.in_(member_proj_ids)
                )
            ).filter(JiraProject.status == status_filter)

    if status_filter != 'all' and current_member.has_permission('MANAGE_PROJECTS'):
        query = query.filter(JiraProject.status == status_filter)

    return query.order_by(JiraProject.created_at.desc()).all()


def get_project_detail(project_id, user_id):
    """获取项目详情"""
    project = JiraProject.query.options(
        db.joinedload(JiraProject.stages),
        db.joinedload(JiraProject.members).joinedload(JiraMember.member),
        db.joinedload(JiraProject.category),
        db.joinedload(JiraProject.level),
        db.joinedload(JiraProject.approval_flow),
        db.joinedload(JiraProject.owner),
        # 性能优化：预加载审批记录和审批人
        db.joinedload(JiraProject.reviews).joinedload(JiraReview.reviewer)
    ).get_or_404(project_id)

    # 检查用户是否有权限访问
    member = AdminMember.query.get(user_id)
    if not member or not member.status:
        raise PermissionError("用户不存在或已被禁用")

    # 检查访问权限：项目成员、项目负责人、评审人或有全局查看权限的管理员
    is_member = any(m.member_id == user_id for m in project.members)
    is_owner = project.owner_id == user_id
    # 性能优化：使用预加载的数据
    is_reviewer = any(review.reviewer_id == user_id for review in project.reviews)
    can_view_all = member.has_permission('VIEW_PROJECTS')

    # 允许项目负责人和成员在任何阶段查看项目
    if not (is_member or is_owner or is_reviewer or can_view_all):
        error_msg = f"用户 {user_id} 无权访问项目 {project_id}。"
        raise PermissionError(error_msg)

    # 计算项目进度
    total_tasks = 0
    completed_tasks = 0
    for stage in project.stages:
        total_tasks += len(stage.tasks)
        completed_tasks += len([task for task in stage.tasks if task.status == 'completed'])

    progress = (completed_tasks / total_tasks * 100) if total_tasks > 0 else 0
    project.progress = progress
    project.total_tasks = total_tasks
    project.completed_tasks = completed_tasks

    return project


def create_jira_project(user_id, form_data):
    """创建新的JIRA项目"""
    name = form_data.get('name')
    if not name:
        raise ValueError("项目名称不能为空")

    # 创建项目
    project = JiraProject(
        name=name,
        description=form_data.get('description'),
        owner_id=user_id,
        submitter_id=user_id,
        status=JiraProject.DRAFT,
        created_at=datetime.now(),
        started_at=form_data.get('start_date'),
        end_date=form_data.get('end_date'),
        category_id=form_data.get('category_id'),
        level_id=form_data.get('level_id'),
        approval_flow_id=form_data.get('approval_flow_id'),
        first_approver_id=form_data.get('first_approver_id')
    )
    db.session.add(project)
    db.session.flush()

    try:
        # 确保owner_id一定会被添加为成员
        member_ids = set(form_data.get('member_ids', []))
        member_ids.add(user_id)

        # 健壮性：验证成员ID是否存在
        valid_members = AdminMember.query.filter(AdminMember.id.in_(member_ids)).all()
        valid_member_ids = {m.id for m in valid_members}

        invalid_ids = member_ids - valid_member_ids
        if invalid_ids:
            logger.warning(f"创建项目 {project.id} 时发现无效的成员ID: {invalid_ids}")

        # 批量添加有效成员
        members = [
            JiraMember(project_id=project.id, member_id=member_id)
            for member_id in valid_member_ids
        ]
        if members:
            db.session.bulk_save_objects(members)

    except Exception as e:
        db.session.rollback()
        logger.error(f"添加项目成员失败: {str(e)}")
        raise ValueError("项目创建失败，请重试")

    # 添加默认阶段
    default_stages = [
        ("项目启动", "定义项目目标、范围和关键利益相关者"),
        ("项目规划", "制定详细的项目计划、时间表和资源分配"),
        ("项目执行", "按照计划执行项目任务和活动"),
        ("项目监控", "跟踪项目进展、管理风险和变更"),
        ("项目收尾", "完成交付、总结经验并正式结束项目")
    ]

    for order, (name, desc) in enumerate(default_stages):
        db.session.add(JiraStage(
            project_id=project.id,
            name=name,
            description=desc,
            order=order
        ))

    db.session.commit()
    return project


def update_jira_project(project_id, user_id, form_data):
    """更新JIRA项目"""
    project = JiraProject.query.get_or_404(project_id)

    # 检查权限
    if project.owner_id != user_id:
        raise PermissionError("只有项目负责人可以编辑项目")

    # 检查状态
    if project.status not in [JiraProject.DRAFT, JiraProject.REJECTED]:
        raise ValueError("只有草稿或被拒绝状态的项目可以编辑")

    # 获取表单数据
    name = form_data.get('name')
    if not name:
        raise ValueError("项目名称不能为空")

    # 更新项目基本信息
    project.name = name
    project.description = form_data.get('description')
    project.started_at = form_data.get('start_date')
    project.end_date = form_data.get('end_date')
    project.category_id = form_data.get('category_id')
    project.level_id = form_data.get('level_id')
    project.approval_flow_id = form_data.get('approval_flow_id')
    project.first_approver_id = form_data.get('first_approver_id')
    project.updated_at = datetime.now()
    # 如果项目是被拒绝状态，编辑后重置为草稿状态
    if project.status == JiraProject.REJECTED:
        project.status = JiraProject.DRAFT

    try:
        # 确保负责人始终在成员列表中
        target_member_ids = set(form_data.get('member_ids', []))
        target_member_ids.add(user_id)

        # 获取当前项目成员ID列表
        current_member_ids = {m.member_id for m in project.members}

        # 找出需要删除的成员
        members_to_remove = current_member_ids - target_member_ids
        if members_to_remove:
            JiraMember.query.filter(
                JiraMember.project_id == project_id,
                JiraMember.member_id.in_(members_to_remove)
            ).delete(synchronize_session=False)

        # 找出需要添加的成员
        members_to_add_ids = target_member_ids - current_member_ids
        if members_to_add_ids:
            # 健壮性：验证成员ID是否存在
            valid_new_members = AdminMember.query.filter(AdminMember.id.in_(members_to_add_ids)).all()
            valid_new_member_ids = {m.id for m in valid_new_members}

            invalid_ids = members_to_add_ids - valid_new_member_ids
            if invalid_ids:
                logger.warning(f"更新项目 {project.id} 时发现无效的成员ID: {invalid_ids}")

            new_members = [
                JiraMember(project_id=project.id, member_id=member_id)
                for member_id in valid_new_member_ids
            ]
            if new_members:
                db.session.bulk_save_objects(new_members)

        db.session.commit()
        return project

    except Exception as e:
        db.session.rollback()
        logger.error(f"更新项目失败: {str(e)}")
        raise ValueError("项目更新失败，请重试")


def delete_project(project_id, user_id):
    """删除项目"""
    project = JiraProject.query.get_or_404(project_id)

    # 检查权限
    if project.owner_id != user_id:
        raise PermissionError("只有项目负责人可以删除项目")

    # 状态检查
    if project.status not in [JiraProject.DRAFT, JiraProject.REJECTED]:
        raise ValueError("只有草稿或被拒绝状态的项目可以删除")

    return project

# 测试相关函数
def create_test_project():
    """创建测试项目并配置审批流程"""
    try:
        # 创建审批流程
        approval_flow = JiraApprovalFlow(
            name="测试审批流程",
            description="用于测试的审批流程"
        )
        db.session.add(approval_flow)
        db.session.flush()  # 保存以获取ID

        # 创建两个审批步骤
        # 第一步审批人 - 假设ID为1的用户
        step1 = JiraApprovalStep(
            flow_id=approval_flow.id,
            order=1,
            reviewer_id=1,  # 第一个审批人
            name="技术评审"
        )

        # 第二步审批人 - 假设ID为2的用户
        step2 = JiraApprovalStep(
            flow_id=approval_flow.id,
            order=2,
            reviewer_id=2,  # 第二个审批人
            name="管理评审"
        )

        db.session.add_all([step1, step2])

        # 创建测试项目
        project = JiraProject(
            name="测试项目",
            description="用于测试审批流程的项目",
            status="draft",
            approval_flow_id=approval_flow.id
        )
        db.session.add(project)
        db.session.commit()

        return {
            'project_id': project.id,
            'approval_flow_id': approval_flow.id,
            'step1_id': step1.id,
            'step2_id': step2.id
        }

    except Exception as e:
        db.session.rollback()
        logger.error(f"创建测试项目失败: {str(e)}")
        raise

def submit_test_approval(project_id, submitter_id=1):
    """提交测试审批请求"""
    try:
        from member.approval.services import submit_approval
        form_data = {
            'project_id': project_id,
            'notes': '测试审批请求'
        }
        return submit_approval(submitter_id, form_data)
    except Exception as e:
        logger.error(f"提交测试审批失败: {str(e)}")
        raise

def approve_step(approval_id, reviewer_id, action='approve', notes=''):
    """处理审批步骤"""
    try:
        from member.approval.services import review_approval
        return review_approval(approval_id, reviewer_id, action, notes)
    except Exception as e:
        logger.error(f"处理审批步骤失败: {str(e)}")
        raise

def get_project_status(project_id):
    """获取项目状态"""
    project = JiraProject.query.get(project_id)
    if project:
        return project.status
    return None